const {ipcRenderer} = require('electron');
const EventEmitter = require('events');

const {log, logError} = require('../../../utils/log');
const signalTypes = require('../../../signal_types');

const dc_ee = new EventEmitter();

const initPeerControl = async (be_controlled_code) => {
  const pc = new window.RTCPeerConnection({
    iceServers: [
      {
        urls: 'stun:stun.l.google.com:19302'
      }
    ]
  });
  window.pc = pc;

  // 建立dc通道 用以传输指令
  // todo 建立更多的dc通道 分别用以传输文字、文件、白板指令等
  const dc = pc.createDataChannel(
    'robotChannel',
    {
      reliable: false  //允许一定的丢失
    })
  window.dc = dc;
  dc.onopen = function (e) {
    log('dc.onopen ---> e:',e)
    dc_ee.on('robot', (type, data) => {
      // log(`dc.send robot ---> type:${type} data:`, data);
      dc.send(JSON.stringify({type, data}));
    });
  };
  dc.onmessage = function(e){
    log('dc.onmessage ---> e:', e);
  }
  dc.onerror = e => logError('dc.onerror ---> e:', e);


  pc.onicecandidate = function (e) {
    log('【onicecandidate】 e:', e);
    log('pc.onicecandidate ---> find a new candidate:', e.candidate);

    // 如果是null,意味着已经搜集完毕了
    if (e.candidate) {
      ipcRenderer.send(signalTypes["SIGNAL_SERVER:CONTROL:FORWARD"], 'control-candidate', be_controlled_code, JSON.stringify(e.candidate));
    }
  };

  const onCandidate = (e,candidate)=>{
    log('addIceCandidate:', candidate);
    addIceCandidate(candidate);
  }

  ipcRenderer.on('candidate', onCandidate);

  const candidates = [];
  async function addIceCandidate(candidate) {
    if(!candidate ) return

    candidates.push(candidate)
    //`addIceCandidate`必须在调用`setRemoteDescription`之后使用,
    // 否则会报错: [12544:0813/220913.805:ERROR:sdp_offer_answer.cc(2280)] AddIceCandidate: ICE candidates can't be added without any remote session description.
    if(pc.remoteDescription && pc.remoteDescription.type) {
      for(let i = 0; i < candidates.length; i ++) {
        await pc.addIceCandidate(new RTCIceCandidate(JSON.parse(candidates[i])))
      }
      candidate.length = 0;
    }
  }

  const onAnswer = (e,answer)=>{
    log('received answer, is sending to remote:', answer);
    setRemote(answer);
  }
  // window.setRemote = setRemote;
  ipcRenderer.on('answer', onAnswer);
  async function setRemote(answer){
    await pc.setRemoteDescription(answer);
  }

  const video = document.getElementById('screen-video');
  pc.ontrack = function(e){
    log('pc.ontrack received track:',e);
    log('e.streams:',e.streams);
    video.srcObject = e.streams[0];
  }

  createOfferAndSend();
  async function createOfferAndSend(){
    log('pc.createOffer--- --- ---');
    const offer = await pc.createOffer({
      offerToReceiveAudio: false,
      offerToReceiveVideo: true
    });
    log('created offer:', offer);
    log('pc.setLocalDescription--- --- ---');
    await pc.setLocalDescription(offer);

    ipcRenderer.send(signalTypes["SIGNAL_SERVER:CONTROL:FORWARD"], 'offer', be_controlled_code,{type: offer.type, sdp: offer.sdp});
  }

  const clear = () => {
    ipcRenderer.off('answer', onAnswer);
    ipcRenderer.off('candidate', onCandidate);
  };
  return {
    clear,
    pc
  }
};

module.exports = {
  initPeerControl,
  dc_ee
};
